#include<iostream>
#include<string>
#include<cassert>
#include<typeinfo>
#include<typeindex>
#include<unistd.h>

class Any{
public:
    Any():_content(NULL){}
    template<typename T>
    Any(const T &val):_content(new holder<T>(val)){}
    Any(const Any &other):_content(other._content?other._content->clone():NULL) {}
    ~Any() { if(_content) delete _content; }
    const std::type_info &type(){ return _content? _content->type() : typeid(void); }
    Any &swap(Any &other){
        std::swap(_content,other._content);
        return *this;
    }
    template<typename T>
    T *get() {
        assert(typeid(T)==_content->type());
        return &((holder<T>*)_content)->val;
    }
    template<typename T>
    Any &operator=(const T &val){
        Any(val).swap(*this);//自己与Any(val)
        return *this;
    }
    Any &operator=(Any other){
        other.swap(*this);
        return *this;
    }

private:
    class placeholder{
        public:
            virtual ~placeholder(){}
            virtual const std::type_info &type() = 0;
            virtual placeholder *clone() = 0; 
    };
    template<typename T>// holder对象
    class holder : public placeholder{
        public:
            holder(const T &v):val(v){}
            ~holder(){}
            const std::type_info &type() { return typeid(T);}
            placeholder *clone() { return new holder(val);}
        public:
            T val;
    };
    placeholder *_content;
};

class Test{
public:
    std::string _data;
public:
    Test(const std::string &data):_data(data){
        std::cout<<"构造"<<_data<<std::endl;
    }
    Test(const Test &other){
        _data = other._data;
        std::cout<<"拷贝"<<_data<<std::endl;
    } 
    ~Test() { std::cout<< "析构"<< _data << std::endl; }
};

int main(){
    int a=10;
    float b=20;
    std::string c="Hello World";
    Any any_a(a);
    Any any_b(b);
    Any any_c(c);
    int *aa = any_a.get<int>();
    float *bb = any_b.get<float>();
    std::string *cc = any_c.get<std::string>();
    
    std::cout<<*aa<<std::endl;
    std::cout<<*bb<<std::endl;
    std::cout<<*cc<<std::endl;
    return 0;
}